home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Online / SpeakFreely / src / lwl.c < prev    next >
C/C++ Source or Header  |  2000-05-18  |  12KB  |  468 lines

  1. /*
  2.  
  3.             Speak Freely for Unix
  4.                      Look Who's Listening Client
  5.  
  6. */
  7.  
  8. #include "speakfree.h"
  9. #include "version.h"
  10.  
  11. static int sock;              /* Our socket */
  12. static char *prog;              /* Program name */ 
  13.  
  14. static struct sockaddr_in lookhost;   /* Look who's listening host, if any */
  15. static int lwlport = Internet_Port + 2; /* Look Who's Listening port */
  16. static int debugging = FALSE;          /* Debug mode enabled */
  17. static int showmessage = FALSE;       /* Show server message */
  18.  
  19. struct lwl {
  20.     struct lwl *next;              /* Next connection */
  21.     long ltime;               /* Time of last update */
  22.     unsigned long ssrc;           /* Session source descriptor */
  23.     long naddr;               /* Internet address */
  24.     short port;               /* Port address */
  25.     char *cname;              /* Canonical name */ 
  26.     char *name;               /* User name */
  27.     char *email;              /* Electronic mail address */
  28.     char *phone;              /* Telephone number */
  29.     char *loc;                  /* Geographic location */
  30.     char *tool;               /* Application name */
  31. };
  32.  
  33. /*  PROG_NAME  --  Extract program name from argv[0].  */
  34.  
  35. static char *prog_name(arg)
  36.   char *arg;
  37. {
  38.     char *cp = strrchr(arg, '/');
  39.  
  40.     return (cp != NULL) ? cp + 1 : arg;
  41. }
  42.  
  43. /*  USAGE  --  Print how-to-call information.  */
  44.  
  45. static void usage()
  46. {
  47.     V fprintf(stderr, "%s  --  Speak Freely: Look Who's Listening Lookup.\n", prog);
  48.     V fprintf(stderr, "               %s.\n", Relno);
  49.     V fprintf(stderr, "\n");
  50.     V fprintf(stderr, "Usage: %s [options]\n", prog);
  51.     V fprintf(stderr, "Options:\n");
  52.     V fprintf(stderr, "           -C          Output sfmike connection address(es)\n");
  53.     V fprintf(stderr, "           -D          Debugging output on stderr\n");
  54.     V fprintf(stderr, "           -Hhost:port Query designated host\n");
  55.     V fprintf(stderr, "           -L          List table of matches\n");
  56.     V fprintf(stderr, "           -M          Show server message\n");
  57.     V fprintf(stderr, "           -U          Print this message\n");
  58.     V fprintf(stderr, "\n");
  59.     V fprintf(stderr, "by John Walker\n");
  60.     V fprintf(stderr, "   http://www.fourmilab.ch/\n");
  61. }
  62.  
  63. /*  DUPSDESITEM  --  Make a copy of an SDES item and advance the pointer
  64.              past it.  */
  65.  
  66. static char *dupSdesItem(cp)
  67.   char **cp;
  68. {
  69.     char *ip = *cp, *bp;
  70.     int l = ip[1] & 0xFF;
  71.  
  72.     bp = malloc(l + 1);
  73.     if (bp != NULL) {
  74.     bcopy(ip + 2, bp, l);
  75.     bp[l] = 0;
  76.     }
  77.     *cp = ip + l + 2;
  78.     return bp;
  79. }
  80.  
  81. /*  DESTROYLWL    --  Release storage associated with an LWL list item.  */
  82.  
  83. static void destroyLwl(lw)
  84.   struct lwl *lw;
  85. {
  86.     if (lw->cname != NULL) {
  87.     free(lw->cname);
  88.     }
  89.     if (lw->name != NULL) {
  90.     free(lw->name);
  91.     }
  92.     if (lw->email != NULL) {
  93.     free(lw->email);
  94.     }
  95.     if (lw->phone != NULL) {
  96.     free(lw->phone);
  97.     }
  98.     if (lw->loc != NULL) {
  99.     free(lw->loc);
  100.     }
  101.     if (lw->tool != NULL) {
  102.     free(lw->tool);
  103.     }
  104.     free(lw);
  105. }
  106.  
  107. /*  DUMPLWL  --  Dump an LWL on the specified stream.  */
  108.  
  109. static void dumpLwl(fo, lw)
  110.   FILE *fo;
  111.   struct lwl *lw;
  112. {
  113.     struct sockaddr_in s;
  114.  
  115.     s.sin_addr.s_addr = lw->naddr;
  116.     fprintf(fo, "SSRC = %X IP = %s Port %d %s", lw->ssrc, inet_ntoa(s.sin_addr),
  117.         lw->port, ctime(&(lw->ltime)));
  118.     if (lw->cname != NULL) {
  119.         fprintf(fo, "    CNAME = %s\n", lw->cname);
  120.     }
  121.     if (lw->name != NULL) {
  122.         fprintf(fo, "     NAME = %s\n", lw->name);
  123.     }
  124.     if (lw->email != NULL) {
  125.         fprintf(fo, "    EMAIL = %s\n", lw->email);
  126.     }
  127.     if (lw->phone != NULL) {
  128.         fprintf(fo, "    PHONE = %s\n", lw->phone);
  129.     }
  130.     if (lw->loc != NULL) {
  131.         fprintf(fo, "      LOC = %s\n", lw->loc);
  132.     }
  133.     if (lw->tool != NULL) {
  134.         fprintf(fo, "     TOOL = %s\n", lw->tool);
  135.     }
  136. }
  137.  
  138. /*  Main program.  */
  139.  
  140. main(argc, argv)
  141.   int argc;
  142.   char *argv[];
  143. {
  144.     int i, argie, length, nret = 0, connex = FALSE,
  145.     listing = FALSE, deefault = TRUE;
  146.     struct sockaddr_in name;
  147.     char *hostspec = NULL, *cp;
  148.  
  149.     /*    Process command line options.  */
  150.  
  151.     prog = prog_name(argv[0]);
  152.     for (argie = 1; argie < argc; argie++) {
  153.     char *op, opt;
  154.  
  155.     op = argv[argie];
  156.         if (*op == '-') {
  157.         opt = *(++op);
  158.         if (islower(opt)) {
  159.         opt = toupper(opt);
  160.         }
  161.  
  162.         switch (opt) {
  163.                 case 'C':             /* -C  --  Output connect addresses */
  164.             connex = TRUE;
  165.             deefault = FALSE;
  166.             break;
  167.  
  168.                 case 'D':             /* -D  --  Debug output to stderr */
  169.             debugging = TRUE;
  170.             break;
  171.  
  172.                 case 'H':             /* -Hhost:port  --  Host/port to query */
  173.             hostspec = op + 1;
  174.             break;
  175.  
  176.                 case 'L':             /* -L  --  List table of finds  */
  177.             listing = TRUE;
  178.             deefault = FALSE;
  179.             break;
  180.  
  181.                 case 'M':             /* -M  --  Show server message */
  182.             showmessage = TRUE;
  183.             break;
  184.  
  185.                 case 'U':             /* -U  --  Print usage information */
  186.                 case '?':             /* -?  --  Print usage information */
  187.             usage();
  188.             return 0;
  189.         }
  190.     } else {
  191.         break;
  192.     }
  193.     }
  194.  
  195.     /* Try to locate host to contact for information. */
  196.  
  197.     if ((cp = hostspec) == NULL) {
  198.         cp = getenv("SPEAKFREE_LWL_ASK");
  199.     if (cp == NULL || strlen(cp) == 0) {
  200.         char *np;
  201.  
  202.             cp = getenv("SPEAKFREE_LWL_TELL");
  203.         if (cp == NULL) {
  204.                 fprintf(stderr, "%s: no host specified.\n", prog);
  205.                 fprintf(stderr, "%s: use -Hhost:port option or SPEAKFREE_LWL_ASK\n", prog);
  206.                 fprintf(stderr, "%s: or SPEAKFREE_LWL_TELL environment variables.\n", prog);
  207.         return 2;
  208.         }
  209.  
  210.         /* Multiple hosts may have been specified on the
  211.            SPEAKFREE_LWL_TELL statement.  If so, query only the
  212.            first. */
  213.  
  214.             if ((np = strchr(cp, ',')) != NULL) {
  215.         *np = 0;
  216.         }
  217.     }
  218.     }
  219.  
  220.     if (cp != NULL) {
  221.     struct hostent *h;
  222.     char *ep;
  223.  
  224.         if ((ep = strchr(cp, ':')) != NULL) {
  225.         *ep = 0;
  226.         lwlport = atoi(ep + 1);
  227.     }
  228.     h = gethostbyname(cp);
  229.     if (h != NULL) {
  230.         bcopy((char *) (h->h_addr), (char *) &lookhost.sin_addr.s_addr,
  231.         sizeof lookhost.sin_addr.s_addr);
  232.         lookhost.sin_family = AF_INET;
  233.         lookhost.sin_port = htons(lwlport);
  234.     } else {
  235.             fprintf(stderr, "%s: server %s is unknown.\n", prog, cp);
  236.         return 2;
  237.     }
  238.     }
  239.  
  240.     /* Now loop through the command line arguments and pose
  241.        each as a query to the server, then print whatever
  242.        reply we get. */
  243.  
  244.     for (; showmessage || (argie < argc); argie++) {
  245.     char p[1500];
  246.     rtcp_t *rp = (rtcp_t *) p;
  247.         static char query[] = "SFlq";
  248.     int l;
  249.     char *cp;
  250.  
  251.     /* Create the socket */
  252.  
  253.     sock = socket(AF_INET, SOCK_STREAM, 0);
  254.     if (sock < 0) {
  255.             perror("opening stream socket");
  256.         return 1;
  257.     }
  258.  
  259.     if (connect(sock, (struct sockaddr *) &lookhost, sizeof lookhost) < 0) {
  260.             perror("connecting stream socket");
  261.         return 1;
  262.     }
  263.  
  264.     /* Find assigned port value and print it. */
  265.  
  266.     length = sizeof(name);
  267.     if (getsockname(sock, (struct sockaddr *) &name, &length) < 0) {
  268.             perror("getting socket name");
  269.         return 1;
  270.     }
  271. #ifdef SHOW_SOCKET
  272.         fprintf(stderr, "%s: socket port #%d\n", prog, ntohs(name.sin_port));
  273. #endif
  274.  
  275. #ifdef RationalWorld
  276.     rp->common.version = RTP_VERSION;
  277.     rp->common.p = 0;
  278.     rp->common.count = 1;
  279.     rp->common.pt = RTCP_APP;
  280. #else
  281.     *((short *) rp) = htons((RTP_VERSION << 14) | RTCP_APP | (1 << 8));
  282. #endif
  283.     rp->r.sdes.src = 0;
  284.     if (showmessage) {
  285.         argie--;
  286.             bcopy("SFms", p + 8, 4);
  287.         rp->common.length = htons(2);
  288.         if (send(sock, p, 12, 0) < 0) {
  289.                 perror("sending server message request");
  290.         }
  291.     } else {
  292.         bcopy(query, p + 8, 4);
  293.         strcpy(p + 12, argv[argie]);
  294.         cp = p + 13 + strlen(p + 12);
  295.         while ((cp - p) & 3) {
  296.         *cp++ = 0;
  297.         }
  298.         rp->common.length = htons(((cp - p) / 4) - 1);
  299.         if (send(sock, p, cp - p, 0) < 0) {
  300.                 perror("sending look who's listening query message");
  301.         }
  302.     }
  303.  
  304.     if ((l = recv(sock, p, sizeof p, 0)) > 0) {
  305.         if (showmessage) {
  306.         showmessage = FALSE;
  307.         fwrite(p + 12, l - 13, 1, stdout);
  308.         } else {
  309.         int sdes_count;
  310.  
  311. #ifdef RationalWorld
  312.         sdes_count = rp->common.count;
  313. #else
  314.         sdes_count = (((unsigned char *) rp)[0]) & 0x1F;
  315. #endif
  316.         cp = (char *) &(rp->r.sdes.src);
  317.         while (sdes_count-- > 0) {
  318.             struct lwl *lw;
  319.  
  320.             lw = (struct lwl *) malloc(sizeof(struct lwl));
  321.             if (lw != NULL) {
  322.             int parsing = TRUE;
  323.             struct sockaddr_in u;
  324.             char s[40];
  325.  
  326.             bzero((char *) lw, sizeof(struct lwl));
  327.  
  328.             bcopy(cp, (char *) &(lw->ssrc), 4);
  329.             cp += 4;
  330.  
  331.             while (parsing) {
  332.                 switch ((*cp) & 0xFF) {
  333.  
  334.                 case RTCP_SDES_CNAME:
  335.                     lw->cname = dupSdesItem(&cp);
  336.                     break;
  337.  
  338.                 case RTCP_SDES_NAME:
  339.                     lw->name = dupSdesItem(&cp);
  340.                     break;
  341.  
  342.                 case RTCP_SDES_EMAIL:
  343.                     lw->email = dupSdesItem(&cp);
  344.                     break;
  345.  
  346.                 case RTCP_SDES_PHONE:
  347.                     lw->phone = dupSdesItem(&cp);
  348.                     break;
  349.  
  350.                 case RTCP_SDES_LOC:
  351.                     lw->loc = dupSdesItem(&cp);
  352.                     break;
  353.  
  354.                 case RTCP_SDES_TOOL:
  355.                     lw->tool = dupSdesItem(&cp);
  356.                     break;
  357.  
  358.                 case RTCP_SDES_PRIV:
  359.                     {
  360.                     char *zp = dupSdesItem(&cp);
  361.  
  362.                     if (zp != NULL) {
  363.                         if (zp[0] == 1 &&
  364.                                                 zp[1] == 'P') {
  365.                         lw->port = atoi(zp + 2);
  366.                         } else if (zp[0] == 1 &&
  367.                                                        zp[1] == 'I') {
  368.                         lw->naddr = inet_addr(zp + 2);
  369.                         }  else if (zp[0] == 1 &&
  370.                                                         zp[1] == 'T') {
  371.                         lw->ltime = atol(zp + 2);
  372.                         }
  373.                         free(zp);
  374.                     }
  375.                     }
  376.                     break;
  377.  
  378.                 case RTCP_SDES_END:
  379.                     cp++;
  380.                     while ((cp - p) & 3) {
  381.                     cp++;
  382.                     }
  383.                     parsing = FALSE;
  384.                     break;
  385.  
  386.                 default:
  387.                     {
  388.                     char *zp = dupSdesItem(&cp);
  389.  
  390.                     if (zp != NULL) {
  391.                         free(zp);
  392.                     }
  393.                     }
  394.                     break;
  395.                 }
  396.             }
  397.             if (debugging) {
  398.                 dumpLwl(stderr, lw);
  399.             }
  400.             u.sin_addr.s_addr = lw->naddr;
  401.  
  402.             /* Default output listing: short address/cname (name) list. */
  403.  
  404.             if (deefault) {
  405.                 char ipport[40], deef[256];
  406.  
  407.                             sprintf(ipport, "%s:%d", inet_ntoa(u.sin_addr), lw->port);
  408.                             sprintf(deef, "%-24s %s", ipport, lw->cname);
  409.                 if (lw->name) {
  410.                                 sprintf(deef + strlen(deef), " (%s)", lw->name);
  411.                 }
  412.                             printf("%s\n", deef);
  413.             }
  414.  
  415.             /* Output connect IP:port arguments if requested. */
  416.  
  417.             if (connex) {
  418.                             printf("%s-p%s:%d", nret > 0 ? " " : "",
  419.                 inet_ntoa(u.sin_addr), lw->port);
  420.             }
  421.  
  422.             /* Produce long tabular listing of results.  */
  423.  
  424.             if (listing) {
  425.                 char ipport[40];
  426.                 struct tm *lt;
  427.  
  428.                 lt = localtime(&lw->ltime);
  429.                             sprintf(ipport, "%s:%d", inet_ntoa(u.sin_addr), lw->port);
  430.                             printf("\n%-24s %-48s %02d:%02d\n", ipport, lw->cname,
  431.                 lt->tm_hour, lt->tm_min);
  432.                 if (lw->name != NULL) {
  433.                                 printf("%25s%s\n", "", lw->name);
  434.                 }
  435.                 if (lw->loc != NULL) {
  436.                                 printf("%25s%s\n", "", lw->loc);
  437.                 }
  438.                 if (lw->phone != NULL) {
  439.                                 printf("%25sPhone:  %s\n", "", lw->phone);
  440.                 }
  441.                 if (lw->email != NULL) {
  442.                                 printf("%25sE-mail: %s\n", "", lw->email);
  443.                 }
  444.             }
  445.  
  446.             nret++;
  447.             destroyLwl(lw);
  448.             }
  449.         }
  450.         }
  451.     }
  452.     if (l <= 0) {
  453.             perror("reading reply from socket");
  454.         return 2;
  455.     }
  456.     close(sock);
  457.     }
  458.     if (connex) {
  459.     if (nret > 0) {
  460.             printf("\n");
  461.     } else {
  462.             fprintf(stderr, "No users found.\n");
  463.         return 2;
  464.     }
  465.     }
  466.     return 0;
  467. }
  468.